﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using Noris.Tools.TraceVisualiser.Interface;
using Noris.Tools.TraceVisualiser.Support;
using Noris.Tools.TraceVisualiser.TraceData;
using Noris.Tools.TraceVisualiser.Components;
using Noris.Tools.TraceVisualiser.Forms;
using Noris.Tools.TraceVisualiser.Components;

namespace Noris.Tools.TraceVisualiser.Green.DbBlocking
{
	#region EventItem : data jedné události v trace souboru blokování
	/// <summary>
    /// EventItem : data jedné události v trace souboru blokování
    /// </summary>
    internal class EventItem : IEventItem, TraceVisualiser.Forms.IMasterDetails
    {
        #region Vytvoření instance - tato třída se vytváří přímo z textu řádku, bez přechodu přes objekt TraceItem
		/// <summary>
		/// Vytvoří a vrátí objekt EventItem, anebo null pokud není korektní zadání
		/// </summary>
		/// <param name="stringHeap"></param>
		/// <param name="traceInfo">Soubor Trace</param>
		/// <param name="lineNumber">Číslo řádky</param>
		/// <param name="lineText">Text řádky</param>
		/// <param name="persistData">Trvalá data ze serveru</param>
		/// <returns></returns>
        internal static EventItem CreateItem(StringHeap stringHeap, TraceInfo traceInfo, int lineNumber, string lineText, ref TraceServerPersistData persistData)
        {
			if (stringHeap == null || traceInfo == null || lineText.IsEmpty())
				return null;

            EventItem info = new EventItem(stringHeap);
			info.ParseLine(traceInfo, lineNumber, lineText, ref persistData);
			if (!info.LineIsParsed)
				return null;
			return info;
        }
        private EventItem(StringHeap stringHeap)
        {
            this.StringHeap = stringHeap;
            this.Time = TimeRange.Empty;
			this.Process1Blocked = new TraceItemBlock(stringHeap);
			this.Process2Active = new TraceItemBlock(stringHeap);
            this.Properties = ElementProperties.Selectable;
			this.LineNumber = 0;
            this.BackColor = Color.Empty;
        }
        protected StringHeap StringHeap;
        #endregion
	    #region Plnění objektu Event z dat vstupního řádku
		/// <summary>
		/// Do objektu this vepíše data z příchozí události (řádek z trace souboru)
		/// </summary>
		/// <param name="traceInfo">Soubor Trace</param>
		/// <param name="lineNumber">Číslo řádky</param>
		/// <param name="lineText">Text řádky</param>
		/// <param name="persistData">Trvalá data ze serveru</param>
		protected virtual void ParseLine(TraceInfo traceInfo, int lineNumber, string lineText, ref TraceServerPersistData persistData)
        {
			if (String.IsNullOrEmpty(lineText)) return;

			// Struktura řádku:
			//	id;blocked;blocking;dbname;objname_indname;blcktime;type;mode;status;loginame;type2;mode2;status2;loginame2;blcktime2;currenttime;rsc_bin;lasttime;updating;total_blcktime;resource;indid;blocked_cmd;blocking_cmd;fnc;fnc2;fnc_name;fnc_name2;started;started2;ended;ended2;stav;stav2;aitems;aitems2;note;note2;auditlog;auditlog2;noris_user;noris_user2;totally_blocked;program_name;program_name2;session_id;session_id2;user_id;user_id2
			string[] items = lineText.Split(';');
			int length = items.Length;
			if (length < 49)
				return;

			// Parsování:
			Int32.TryParse(items[0], out this._Id);
			this.Process1Blocked.ParseData(items[1], items[5], items[6], items[7], items[8], items[9], items[22], items[24], items[26], items[28], items[30], items[32], items[34], items[36], items[38], items[40], items[43], items[45], items[47]);
			this.Process2Active.ParseData(items[2], items[14], items[10], items[11], items[12], items[13], items[23], items[25], items[27], items[29], items[31], items[33], items[35], items[37], items[39], items[41], items[44], items[46], items[48]);
			this.CurrentTime = MainInfo.ConvertDateTime(items[15]);       // currenttime = Čas prvního zjištění blokování.
			this.LastTime = MainInfo.ConvertDateTime(items[17]);          // lasttime = Čas posledního výskytu blokování na daném zdroji (resource).
			this.DbNameInt32 = this.StringHeap.GetInt32(items[3]);
			string[] names = items[4].Split(' ');                         // objname může obsahovat název tabulky, mezeru a název indexu
			this.ObjNameInt32 = this.StringHeap.GetInt32(names[0]);       // tabulka
			this.IdxNameInt32 = this.StringHeap.GetInt32((names.Length >= 2 ? names[1] : null));   // index
			Int32.TryParse(items[18], out this._Updating);
			Int32.TryParse(items[19], out this._TotalBlcktime);
			Int32.TryParse(items[20], out this._Resource);
			Int32.TryParse(items[21], out this._IndId);
			Int32.TryParse(items[42], out this._TotallyBlocked);

			// Určení času blokování: blokování bylo poprvé zjištěno v čase currenttime a naposledy v čase lasttime.
			// Přičemž blokování při posledním zjištění tvalo čas total_blcktime [milisec].
			// Časový úsek je tedy dán časem End = lasttime, a trváním total_blcktime:
			this.Time = new TimeRange(this.LastTime.AddMilliseconds(-this.TotalBlcktime), this.LastTime);

			// Celková doba threadu ovlivní barevnost:
			// Barvy budou plynule přechodové, což zajistí ColorBlend:
			LinearColorBlender lcb = Steward.GetFromCache(typeof(ThreadColorBlender)) as LinearColorBlender;   // ThreadColorBlender je v systémové cache. Při prvním použití je vytvořen a inicializován (viz definice třídy ThreadColorBlender).
			this.BackColor = lcb.Get((float)this.Time.Seconds, Color.LightGray);

			// Cíl elementu:
			this.TargetHomeNode = null;
			this.TargetPaths = new string[] { NorisBlockingConstants.RootNodeBlocking + "\\" + this.DbName + "\\" + this.ObjIdxName };
			this.TreePaths = null;
			this.Trace = traceInfo;

			// Dokončení:
            this.LineNumber = lineNumber;
			this.LineIsParsed = true;
        }
        #endregion
		#region Public datové property

		// Data přímo z textu
		internal TimeRange Time { get; private set; }
		internal int Id { get { return _Id; } }
		internal TraceItemBlock Process1Blocked { get; private set; }
		internal TraceItemBlock Process2Active { get; private set; }
		internal DateTime CurrentTime { get; private set; }
		internal DateTime LastTime { get; private set; }
		internal Int32 DbNameInt32 { get; private set; }
		internal string DbName { get { return this.StringHeap.GetString(DbNameInt32); } }
		internal Int32 ObjNameInt32 { get; private set; }
		internal string ObjName { get { return this.StringHeap.GetString(ObjNameInt32); } }
		internal Int32 IdxNameInt32 { get; private set; }
		internal string IdxName { get { return this.StringHeap.GetString(IdxNameInt32); } }
        /// <summary>
        /// Jméno objektu včetně jména indexu (pokud není empty).
        /// Typicky tedy: "lcs.subjekty", nebo "lcs.subjekty.idx_reference".
        /// </summary>
		internal string ObjIdxName
		{
			get
			{
				string obj = this.ObjName;
				string idx = this.IdxName;
				if (idx.IsEmpty())
					return obj;
				return obj + "." + idx;
			}
		}

		internal int Updating { get { return _Updating; } }
		internal int TotalBlcktime { get { return _TotalBlcktime; } }
		internal int Resource { get { return _Resource; } }
		internal int IndId { get { return _IndId; } }
		internal int TotallyBlocked { get { return _TotallyBlocked; } }

		internal bool LineIsParsed { get; private set; }

		// Data pro zobrazování
		public int LineNumber { get; protected set; }
		public string TargetHomeNode { get; protected set; }
		public string[] TargetPaths { get; protected set; }
		public TreePath[] TreePaths { get; protected set; }
		public string ColorGroup { get; protected set; }
		public int ColorIndex { get; protected set; }
		public int ElementGroup { get; protected set; }
		public GraphElementShapeType ElementShapeType { get; protected set; }
		public ElementProperties Properties { get; protected set; }
		public Color BackColor { get; protected set; }
		public Image ElementImage { get; protected set; }
		public TraceInfo Trace { get; protected set; }

		/// <summary>
		/// Klíč procesu = Databáze (nikoli objekt)
		/// </summary>
		public string ProcessKey { get { return this.DbName; } }
		/// <summary>
		/// Klíč události = Id (jde o jednoznačný klíč z tabulky blokování)
		/// </summary>
		public string EventKey { get { return this.Id.ToString(); } }
        /// <summary>
        /// Vizualizace
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.DbName + ":" + this.ObjIdxName + " " + this.Caption1 + "; " + this.Time.StringFullDetail;
        }
		#endregion
		#region private proměnné: pár jich existovat musí (Int32.TryParse(string, out proměnná)
		private int _Id;
		private int _Updating;
		private int _TotalBlcktime;
		private int _Resource;
		private int _IndId;
		private int _TotallyBlocked;
		/// <summary>
		/// Vrátí SubTimeSort = číslo trace v čase + číslo řádky
		/// </summary>
		/// <returns></returns>
		private int _GetSubTimeSort()
		{
			// Vrací Int32, který obsahuje bit 31 = 0 (kladné číslo), bity 30 ÷ 25 (6 bitů) = číslo TraceOrder, bity 24 ÷ 0 = číslo LineNumbers[0]:
			return (this.Trace == null ? 0 : (this.Trace.TraceOrder & 0x003F) << 25) | (this.LineNumber & 0x00FFFFFF);
		}
		#endregion
		#region class ThreadColorBlender : míchání barev elementů
		/// <summary>
        /// Třída LinearColorBlender, potomek:
        /// - jednak kvůli exaktnímu použití v Cache (1 instance per Type), 
        /// - a jednak kvůli metodě IInitialize.Initialize()
        /// </summary>
        private class ThreadColorBlender : LinearColorBlender, IInitialize
        {
            #region IInitialize Members

            void IInitialize.Initialize()
            {
                // Čas od (sekund), barva platná pro daný čas: (barvy v mezičasech jsou plně interpolovány, barvy v čase před prvním a po posledním čas jsou rovny barvě v mezní pozici):
                this.Add(0F, Color.PaleGreen);
                this.Add(30F, Color.Orange);
                this.Add(120F, Color.Tomato);
                this.Add(480F, Color.Red);
                this.Add(1800F, Color.DeepPink);
            }

            #endregion
        }
        #endregion
        #region Tvorba textu Caption a Tooltip
        /// <summary>
        /// Vrátí sadu textů pro Captions. Nadřízená metoda si z nich vybere text vhodný pro aktuální velikost elementu.
        /// </summary>
        /// <returns></returns>
        protected virtual string[] CreateCaptions()
        {
            string[] captions = new string[] {
				this.Caption1,
				this.Caption2,
				this.Caption3,
				this.Caption4,
				this.Caption5,
				this.Caption6,
				this.Caption8,
				this.Caption9
            };
            return captions;
        }
        /// <summary>
        /// Vrátí ToolTip, vždy když je potřeba.
        /// </summary>
        /// <returns></returns>
        protected virtual string CreateToolTipInfo()
        {
            string eol = Environment.NewLine;
            string toolTip = "Time: " + this.Time.StringFullDetail + eol +
                _GetTraceText() + ";      Id: " + this.Id + eol +
                "Object: " + this.DbName + "." + this.ObjIdxName + eol +
                this.Caption8 + eol +
                eol +
                this.ToolTipFuncInfo +
                "  ACTIVE PROCESS (blocking):  " + this.Process2Active.ToolTipText + eol +
                "  WAITING PROCESS (blocked):  " + this.Process1Blocked.ToolTipText;

            return toolTip;
        }
		internal string Caption1 { get { return this.Process2Active.Caption1 + " => " + this.Process1Blocked.Caption1; } }
		internal string Caption2 { get { return this.Process2Active.Caption2 + " => " + this.Process1Blocked.Caption2; } }
		internal string Caption3 { get { return this.Process2Active.Caption3 + " => " + this.Process1Blocked.Caption3; } }
		internal string Caption4 { get { return this.Process2Active.Caption4 + " => " + this.Process1Blocked.Caption4; } }
		internal string Caption5 { get { return this.Process2Active.Caption5 + " => " + this.Process1Blocked.Caption5; } }
        internal string Caption6 { get { return this.Process2Active.Caption6 + " => " + this.Process1Blocked.Caption6; } }
        internal string Caption8 { get { return this.Process2Active.Caption5 + " (blocking) => (blocked) " + this.Process1Blocked.Caption5; } }
        internal string Caption9 { get { return this.Process2Active.Caption6 + " (blocking) => (blocked) " + this.Process1Blocked.Caption6; } }
        internal string ToolTipFuncInfo
        {
            get 
            {
                if (this.Process2Active.FncExists || this.Process1Blocked.FncExists)
                    return this.Process2Active.ToolTipFuncInfo + " => " + this.Process1Blocked.ToolTipFuncInfo + Environment.NewLine + Environment.NewLine;
                return "";
            }
        }

		private string _GetTraceText()
        {
            if (this.Trace == null) return "TraceFile: ???";
            return "TraceFile: " + this.Trace.FileDirName + ", Line: " + this.LineNumber.ToString();
        }
        #endregion
        #region IEventPointer Members
        string IEventPointer.ProcessKey { get { return this.ProcessKey; } }
        string IEventPointer.EventKey { get { return this.EventKey; } }
        int IEventPointer.LineNumber { get { return this.LineNumber; } }
        #endregion
        #region IEventItem Members
        string IEventItem.MergeKey { get { return null; } }
        string IEventItem.TargetHomeNode { get { return this.TargetHomeNode; } }
        string[] IEventItem.TargetPaths { get { return this.TargetPaths; } }
        TreePath[] IEventItem.TreePaths { get { return this.TreePaths; } }
        TimeRange IEventItem.Time { get { return this.Time; } }
        void IEventItem.AddData(IEventEdge eventEdge, TraceInfo traceInfo)
        {
            
        }
        bool IEventItem.MergeWith(IEventItem nextEventItem) { return false; }
        int IEventItem.ColorIndex { get { return this.ColorIndex; } }
        #endregion
        #region IDataElement Members
        bool IDataElement.ElementVisible { get { return true; } }
        GID IDataElement.GId { get { return GID.Empty; } }                            // Zde není GID uložen, nemohu jej určit, vrátím Empty. On tento objekt de facto není plnohodnotný IDataElement (právě chybějícím GIDem), ale nechce se mi tvořit jiný interface, shodný s IDataElement až na nepřítomnost GIDu...
        TimeRange IDataElement.TimeRange { get { return this.Time; } set { } }
		float IDataElement.ElementHeightRatio { get { return 0f; } }
		bool IDataElement.BeginIsUncertain { get { return false; } }
        bool IDataElement.EndIsUncertain { get { return false; } }
        int IDataElement.SubTimeSort { get { return _GetSubTimeSort(); } }
        bool IDataElement.FullRow { get { return false; } }
        bool IDataElement.HideZeroWidthElementRectangle { get { return false; } }
        float[] IDataElement.Fragments { get { return null; } }
        GraphLayerType IDataElement.ElementLayer { get { return GraphLayerType.ElementItemLayer; } }
        int IDataElement.ElementGroup { get { return this.ElementGroup; } }
        GraphElementShapeType IDataElement.ElementShapeType { get { return this.ElementShapeType; } }
        ElementProperties IDataElement.Properties { get { return this.Properties; } }
        ElementActionType IDataElement.ActionOnDoubleClick { get { return ElementActionType.DefaultByRow; } }
        GraphElementHandler IDataElement.DoubleClick { get { return null; } }
        string IDataElement.ColorGroup { get { return this.ColorGroup; } }
        Color IDataElement.BackColor { get { return this.BackColor; } set { this.BackColor = value; } }
        Color IDataElement.FontColor { get { return Color.Empty; } }
        bool IDataElement.CaptionShowAllways { get { return true; } }
        Image IDataElement.ElementImage { get { return this.ElementImage; } }
        ContentAlignment IDataElement.ImagePivotElementPoint { get { return ContentAlignment.MiddleCenter; } }
        ContentAlignment IDataElement.ImagePivotImagePoint { get { return ContentAlignment.MiddleCenter; } }
        string[] IDataElement.Captions { get { return CreateCaptions(); } }
        string IDataElement.ToolTipInfo { get { return CreateToolTipInfo(); } }
        string IDataElement.GetToolTipInfo(IDataRow rowData) { return null; }
        string IDataElement.GetCaption(IDataRow rowData, float charCount) { return null; }
        void IDataElement.DrawElement(GraphElementPainterArgs args) { }
        #endregion
        #region IDisposable Members
        public void Dispose()
        {
            this.StringHeap = null;
        }
        #endregion
        #region IMasterDetails Members
        string IMasterDetails.MasterName
        {
            get
            {
                return this.Time.Begin + "; " + this.ObjName;
            }
        }
        Color IMasterDetails.DetailBackColor { get { return this.BackColor; } }
        public IEnumerable<MasterDetailItem> Details { get { return this.CreateDetails(); } }
        /// <summary>
        /// Vytvoří, naplní a vrátí seznam informací Details.
        /// postupně volá metody DetailFillTraceTime(); DetailFill(); DetailFillUserData();
        /// </summary>
        /// <returns></returns>
        protected virtual IEnumerable<MasterDetailItem> CreateDetails()
        {
            List<MasterDetailItem> result = new List<MasterDetailItem>();

            this.DetailFillTraceTime(result);
            this.DetailFillItems(result);
            // this.DetailFillUserData(result);

            return result;
        }
        /// <summary>
        /// Do seznamu detailních údajů vepíše položky ze své evidence.
        /// Třída EventItem vkládá tato data: "Trace, LineNumber"
        /// </summary>
        /// <param name="result"></param>
        protected virtual void DetailFillTraceTime(List<MasterDetailItem> result)
        {
            // Trace, lines, time:
            result.Add(new MasterDetailItem("Time", this.Time.StringFullDetail));
            this.DetailFillTraceInfo("", this.Trace, this.LineNumber, result);
        }
        /// <summary>
        /// Do sady řádků (detaily) vloží data o daném trace.
        /// </summary>
        /// <param name="title">SubTitulek: například "", ".Begin", ".End" atd</param>
        /// <param name="traceInfo">Objekt TraceInfo. Může být null.</param>
        /// <param name="lineNumber">Číslo řádku. Pokud bude null, nebude se vypisovat.</param>
        /// <param name="result">Seznam řádků, kam se detaily vkládají.</param>
        protected void DetailFillTraceInfo(string title, TraceInfo traceInfo, Int32? lineNumber, List<MasterDetailItem> result)
        {
            if (traceInfo == null)
            {
                result.Add(new MasterDetailItem("Trace" + title, "???"));
            }
            else
            {
                result.Add(new MasterDetailItem("Trace" + title, traceInfo.FullFileName));
                if (lineNumber.HasValue)
                    result.Add(new MasterDetailItem("Trace" + title + ".Line", lineNumber.Value.ToString()));
            }
        }
        /// <summary>
        /// Do seznamu detailních údajů vepíše položky ze své evidence.
        /// </summary>
        /// <param name="result"></param>
        protected virtual void DetailFillItems(List<MasterDetailItem> result)
        {
            result.Add(new MasterDetailItem("Id", this.Id));
            result.Add(new MasterDetailItem("CurrentTime", this.CurrentTime));
            result.Add(new MasterDetailItem("LastTime", this.LastTime));
            result.Add(new MasterDetailItem("TotalBlcktime", this.TotalBlcktime));
            result.Add(new MasterDetailItem("TotallyBlocked", this.TotallyBlocked));
            result.Add(new MasterDetailItem("DbName", this.DbName));
            result.Add(new MasterDetailItem("ObjName", this.ObjName));
            result.Add(new MasterDetailItem("IdxName", this.IdxName));
            result.Add(new MasterDetailItem("IndId", this.IndId));
            result.Add(new MasterDetailItem("Resource", this.Resource));
            result.Add(new MasterDetailItem("Updating", this.Updating));

			this.Process2Active.DetailFillItems("Blocking (Active)", "  ", "1", result);
            this.Process1Blocked.DetailFillItems("Blocked (Waiting)", "  ", "2", result);
        }
        #endregion
    }
    #endregion
	#region TraceItemBlock : data z jedné položky pro jednu stranu blokování (strany jsou dvě: blokující = aktivní a blokovaná = pasivní). Zde jsou údaje, které evidujeme u každé strany.
	/// <summary>
	/// TraceItemBlock : data z jedné položky pro jednu stranu blokování (strany jsou dvě: blokující = aktivní a blokovaná = pasivní). Zde jsou údaje, které evidujeme u každé strany.
	/// </summary>
	internal class TraceItemBlock
	{
		internal TraceItemBlock(StringHeap stringHeap)
		{
			this.StringHeap = stringHeap;
		}
		private StringHeap StringHeap;

		internal void ParseData(string spid, string blockTime, string type, string mode, string status, string dbLogin, string sqlCommand, string fncNumb, string fncName, string fncStart, string fncEnd, string fncStav, string aItems, string note, string auditlog, string nrsUser, string progName, string sessionId, string nrsUserNumb)
		{
			Int32.TryParse(spid, out _SpId);
			Int32.TryParse(blockTime, out _BlockTime);
			BlockTypeInt32 = this.StringHeap.GetInt32(type);
			BlockModeInt32 = this.StringHeap.GetInt32(mode);
			BlockStatusInt32 = this.StringHeap.GetInt32(status);
			DbLoginInt32 = this.StringHeap.GetInt32(dbLogin);
            SqlCommandInt32 = this.StringHeap.GetInt32(sqlCommand);
            Int32.TryParse(fncNumb, out _FncNumber);
            FncNameInt32 = this.StringHeap.GetInt32(fncName);
            FncStart = MainInfo.ConvertDateTime(fncStart);
            FncEnd = MainInfo.ConvertDateTime(fncEnd);
            FncStavInt32 = this.StringHeap.GetInt32(fncStav);
            AItemsInt32 = this.StringHeap.GetInt32(aItems);
            NoteInt32 = this.StringHeap.GetInt32(note);
            AuditlogInt32 = this.StringHeap.GetInt32(auditlog);
            NrsUserInt32 = this.StringHeap.GetInt32(nrsUser);
            ProgNameInt32 = this.StringHeap.GetInt32(progName);
            SessionIdInt32 = this.StringHeap.GetInt32(sessionId);
            NrsUserNumbInt32 = this.StringHeap.GetInt32(nrsUserNumb);
		}

		internal int SpId { get { return _SpId; } }
		internal Int32 BlockTypeInt32 { get; private set; }
		internal string BlockType { get { return this.StringHeap.GetString(BlockTypeInt32); } }
		internal Int32 BlockModeInt32 { get; private set; }
		internal string BlockMode { get { return this.StringHeap.GetString(BlockModeInt32); } }
		internal Int32 BlockStatusInt32 { get; private set; }
		internal string BlockStatus { get { return this.StringHeap.GetString(BlockStatusInt32); } }
		internal Int32 DbLoginInt32 { get; private set; }
		internal string DbLogin { get { return this.StringHeap.GetString(DbLoginInt32); } }
        internal Int32 SqlCommandInt32 { get; private set; }
        internal string SqlCommand { get { return this.StringHeap.GetString(SqlCommandInt32); } }
        internal bool FncExists { get { return (this.FncNumber != 0 || StringHeap.IsNotEmpty(this.FncNameInt32)); } }
        internal int FncNumber { get { return this._FncNumber; } }
        internal Int32 FncNameInt32 { get; private set; }
        internal string FncName { get { return this.StringHeap.GetString(FncNameInt32); } }
        internal DateTime FncStart { get; private set; }
        internal DateTime FncEnd { get; private set; }
        internal Int32 FncStavInt32 { get; private set; }
        internal string FncStav { get { return this.StringHeap.GetString(FncStavInt32); } }
        internal Int32 AItemsInt32 { get; private set; }
        internal string AItems { get { return this.StringHeap.GetString(AItemsInt32); } }
        internal Int32 NoteInt32 { get; private set; }
        internal string Note { get { return this.StringHeap.GetString(NoteInt32); } }
        internal Int32 AuditlogInt32 { get; private set; }
        internal string Auditlog { get { return this.StringHeap.GetString(AuditlogInt32); } }
        internal Int32 NrsUserInt32 { get; private set; }
        internal string NrsUser { get { return this.StringHeap.GetString(NrsUserInt32); } }
        internal Int32 ProgNameInt32 { get; private set; }
        internal string ProgName { get { return this.StringHeap.GetString(ProgNameInt32); } }
        internal Int32 SessionIdInt32 { get; private set; }
        internal string SessionId { get { return this.StringHeap.GetString(SessionIdInt32); } }
        internal Int32 NrsUserNumbInt32 { get; private set; }
        internal string NrsUserNumb { get { return this.StringHeap.GetString(NrsUserNumbInt32); } }

	
		private int _SpId;
		private int _BlockTime;
        private int _FncNumber;

		internal string Caption1 { get { return this.SpId.ToString(); } }
		internal string Caption2 { get { return this.SpId.ToString() + " (" + this.BlockType + ")" ; } }
		internal string Caption3 { get { return this.SpId.ToString() + " (" + this.BlockType + ":" + this.BlockMode + ")"; } }
		internal string Caption4 { get { return "SPID: " + this.SpId.ToString() + " (" + this.BlockType + ":" + this.BlockMode + ")"; } }
		internal string Caption5 { get { return "SPID: " + this.SpId.ToString() + " [" + this.BlockStatus + "] (" + this.BlockType + ":" + this.BlockMode + ")"; } }
        internal string Caption6 { get { return "SPID: " + this.SpId.ToString() + " [" + this.BlockStatus + "] (" + this.BlockType + ":" + this.BlockMode + ")" + (this.FncExists ? ";  " + this.ToolTipFuncInfo : ""); } }

        internal string ToolTipFuncInfo
        {
            get
            {
                if (!this.FncExists) return "";
                return "Func." + this.FncNumber.ToString() + ": " + this.FncName;
            }
        }
        internal string ToolTipText
        {
            get
            {
                string toolTip = this.Caption5 + Environment.NewLine + this.SqlCommandShort + Environment.NewLine;
                return toolTip;



                StringBuilder sb = new StringBuilder();

                sb.AppendLine(this.Caption5);            // SPID: 1234 [GRANT] (KEY:U)
                sb.AppendLine(this.SqlCommandShort);     // SQL příkaz

                return sb.ToString();



                sb.AppendLine(this.Caption5);

                if (this.FncExists)
                {
                    sb.AppendLine("Function: " + this.FncNumber.ToString() + ": " + this.FncName);
                    sb.AppendLine("FncStart - End: " + FncStart.ToString("yy-MM-dd HH:mm:ss.fff") + " ÷ " + FncEnd.ToString("yy-MM-dd HH:mm:ss.fff"));
                    if (StringHeap.IsNotEmpty(FncStavInt32))
                        sb.AppendLine("FncStav: " + FncStav);
                    sb.AppendLine();
                }
                if (StringHeap.IsNotEmpty(AItemsInt32))
                    sb.AppendLine("AItems: " + AItems);
                if (StringHeap.IsNotEmpty(NoteInt32))
                    sb.AppendLine("Note: " + Note);
                if (StringHeap.IsNotEmpty(AuditlogInt32))
                    sb.AppendLine("Auditlog: " + this.Auditlog);
                if (StringHeap.IsNotEmpty(NrsUserInt32))
                    sb.AppendLine("NrsUser: " + this.NrsUser);
                if (StringHeap.IsNotEmpty(ProgNameInt32))
                    sb.AppendLine("ProgName: " + this.ProgName);
                if (StringHeap.IsNotEmpty(SessionIdInt32))
                    sb.AppendLine("SessionId: " + this.SessionId);
                if (StringHeap.IsNotEmpty(NrsUserNumbInt32))
                    sb.AppendLine("NrsUserNumb: " + this.NrsUserNumb);
                if (StringHeap.IsNotEmpty(SqlCommandInt32))
                    sb.AppendLine(this.SqlCommandShort);

                return sb.ToString();
            }
        }
        internal string SqlCommandShort { get { return TraceSupport.ShortSqlCommandText(this.SqlCommand, 150, 3); } }
		/// <summary>
		/// Do seznamu detailních údajů vepíše položky ze své evidence.
		/// </summary>
		/// <param name="title">Titulkový řádek</param>
		/// <param name="prefix">Prefix před název položek</param>
		/// <param name="result">Seznam detailních položek</param>
		internal virtual void DetailFillItems(string title, string prefix, string postfix, List<MasterDetailItem> result)
		{
			result.Add(new MasterDetailItem("", title));
			result.Add(new MasterDetailItem(prefix + "SpId" + postfix, this.SpId));
            result.Add(new MasterDetailItem(prefix + "Block Type" + postfix, this.BlockType));
            result.Add(new MasterDetailItem(prefix + "Block Mode" + postfix, this.BlockMode));
            result.Add(new MasterDetailItem(prefix + "Block Status" + postfix, this.BlockStatus));
            result.Add(new MasterDetailItem(prefix + "Db Login" + postfix, this.DbLogin));
            if (StringHeap.IsNotEmpty(SqlCommandInt32))
                result.Add(new MasterDetailItem(prefix + "Sql Command" + postfix, this.SqlCommand));
            if (FncNumber != 0)
                result.Add(new MasterDetailItem(prefix + "Fnc Number" + postfix, this.FncNumber));
            if (StringHeap.IsNotEmpty(FncNameInt32))
                result.Add(new MasterDetailItem(prefix + "Fnc Name" + postfix, this.FncName));
            if (StringHeap.IsNotEmpty(FncStavInt32))
                result.Add(new MasterDetailItem(prefix + "Fnc Stav" + postfix, this.FncStav));
            if (this.FncStart.Year > 1900)
                result.Add(new MasterDetailItem(prefix + "Fnc Start" + postfix, this.FncStart));
            if (this.FncEnd.Year > 1900)
                result.Add(new MasterDetailItem(prefix + "Fnc End" + postfix, this.FncEnd));
            if (StringHeap.IsNotEmpty(AItemsInt32))
                result.Add(new MasterDetailItem(prefix + "AItems" + postfix, this.AItems));
            if (StringHeap.IsNotEmpty(NoteInt32))
                result.Add(new MasterDetailItem(prefix + "Note" + postfix, Note));
            if (StringHeap.IsNotEmpty(AuditlogInt32))
                result.Add(new MasterDetailItem(prefix + "Auditlog" + postfix, this.Auditlog));
            if (StringHeap.IsNotEmpty(NrsUserInt32))
                result.Add(new MasterDetailItem(prefix + "NrsUser" + postfix, this.NrsUser));
            if (StringHeap.IsNotEmpty(ProgNameInt32))
                result.Add(new MasterDetailItem(prefix + "ProgName" + postfix, this.ProgName));
            if (StringHeap.IsNotEmpty(SessionIdInt32))
                result.Add(new MasterDetailItem(prefix + "SessionId" + postfix, this.SessionId));
            if (StringHeap.IsNotEmpty(NrsUserNumbInt32))
                result.Add(new MasterDetailItem(prefix + "NrsUserNumb" + postfix, this.NrsUserNumb));
		}
	}
	#endregion
}
